/*
* Copyright 2015 JBoss Inc
*
* Licensed 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 io.apiman.gateway.engine.policies;
import io.apiman.gateway.engine.beans.ApiRequest;
import io.apiman.gateway.engine.beans.ApiResponse;
import io.apiman.gateway.engine.beans.PolicyFailure;
import io.apiman.test.common.mock.EchoResponse;
import io.apiman.test.policies.ApimanPolicyTest;
import io.apiman.test.policies.BackEndApi;
import io.apiman.test.policies.Configuration;
import io.apiman.test.policies.IPolicyTestBackEndApi;
import io.apiman.test.policies.PolicyFailureError;
import io.apiman.test.policies.PolicyTestBackEndApiResponse;
import io.apiman.test.policies.PolicyTestRequest;
import io.apiman.test.policies.PolicyTestRequestType;
import io.apiman.test.policies.PolicyTestResponse;
import io.apiman.test.policies.TestingPolicy;
import java.util.Arrays;
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
/**
* Unit test.
*
* @author eric.wittmann@redhat.com
*/
@TestingPolicy(TransferQuotaPolicy.class)
@SuppressWarnings("nls")
public class TransferQuotaPolicyTest extends ApimanPolicyTest {
@Test
@Configuration("{" +
" \"limit\" : 100," +
" \"direction\" : \"upload\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Day\"," +
" \"headerRemaining\" : \"X-Bytes-Remaining\"," +
" \"headerLimit\" : \"X-Bytes-Limit\"," +
" \"headerReset\" : \"X-Bytes-Reset\"" +
"}")
public void testUploadLimit() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.POST, "/some/resource");
request.body("0123456789");
PolicyTestResponse response = send(request);
EchoResponse echo = response.entity(EchoResponse.class);
Assert.assertNotNull(echo);
Assert.assertEquals("90", response.header("X-Bytes-Remaining"));
Assert.assertEquals("100", response.header("X-Bytes-Limit"));
// Now try sending a few more times to get closer to the limit
for (int i = 0; i < 9; i++) {
response = send(request);
}
echo = response.entity(EchoResponse.class);
Assert.assertNotNull(echo);
Assert.assertEquals("0", response.header("X-Bytes-Remaining"));
Assert.assertEquals("100", response.header("X-Bytes-Limit"));
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
}
}
@Test
@Configuration("{" +
" \"limit\" : 10485760," +
" \"direction\" : \"upload\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Day\"," +
" \"headerRemaining\" : \"X-Data-Remaining\"," +
" \"headerLimit\" : \"X-Data-Limit\"," +
" \"headerReset\" : \"X-Data-Reset\"" +
"}")
public void testLargeUploadLimit() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.POST, "/some/large-resource");
// The 4th of these should exceed our limits
byte [] data = new byte[11000000 / 4];
Arrays.fill(data, (byte) 80);
request.body(new String(data));
PolicyTestResponse response = send(request);
EchoResponse echo = response.entity(EchoResponse.class);
Assert.assertNotNull(echo);
Assert.assertEquals("7735760", response.header("X-Data-Remaining"));
Assert.assertEquals("10485760", response.header("X-Data-Limit"));
send(request);
send(request);
send(request);
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
String remaining = failure.getHeaders().get("X-Data-Remaining");
Assert.assertEquals("-514240", remaining);
}
}
@Test
@Configuration("{" +
" \"limit\" : 1000," +
" \"direction\" : \"download\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Day\"," +
" \"headerRemaining\" : \"X-DBytes-Remaining\"," +
" \"headerLimit\" : \"X-DBytes-Limit\"," +
" \"headerReset\" : \"X-DBytes-Reset\"" +
"}")
@BackEndApi(DownloadTestBackEndApi.class)
public void testDownloadLimit() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.GET, "/some/resource");
request.header("X-Payload-Size", "389");
PolicyTestResponse response = send(request);
Assert.assertNotNull(response.body());
Assert.assertEquals("1000", response.header("X-DBytes-Remaining"));
Assert.assertEquals("1000", response.header("X-DBytes-Limit"));
send(request);
send(request);
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
}
}
@Test
@Configuration("{" +
" \"limit\" : 1000," +
" \"direction\" : \"download\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Minute\"" +
"}")
@BackEndApi(DownloadTestBackEndApi.class)
public void testDownloadLimitNoHeaderConfig() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.GET, "/some/resource");
request.header("X-Payload-Size", "389");
PolicyTestResponse response = send(request);
Assert.assertNotNull(response.body());
Assert.assertEquals("1000", response.header("X-TransferQuota-Remaining"));
Assert.assertEquals("1000", response.header("X-TransferQuota-Limit"));
send(request);
send(request);
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
}
}
@Test
@Configuration("{" +
" \"limit\" : 1000," +
" \"direction\" : \"download\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Day\"," +
" \"headerRemaining\" : \"\"," +
" \"headerLimit\" : \"\"," +
" \"headerReset\" : \"\"" +
"}")
@BackEndApi(DownloadTestBackEndApi.class)
public void testDownloadLimitEmptyHeaderConfig() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.GET, "/some/resource");
request.header("X-Payload-Size", "389");
PolicyTestResponse response = send(request);
Assert.assertNotNull(response.body());
Assert.assertEquals("1000", response.header("X-TransferQuota-Remaining"));
Assert.assertEquals("1000", response.header("X-TransferQuota-Limit"));
send(request);
send(request);
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
}
}
@Test
@Configuration("{" +
" \"limit\" : 500," +
" \"direction\" : \"both\"," +
" \"granularity\" : \"Api\"," +
" \"period\" : \"Day\"," +
" \"headerRemaining\" : \"X-Bytes-Remaining\"," +
" \"headerLimit\" : \"X-Bytes-Limit\"," +
" \"headerReset\" : \"X-Bytes-Reset\"" +
"}")
@BackEndApi(DownloadTestBackEndApi.class)
public void testBothLimit() throws Throwable {
PolicyTestRequest request = PolicyTestRequest.build(PolicyTestRequestType.PUT, "/some/resource");
request.header("X-Payload-Size", "50");
byte [] data = new byte[50];
Arrays.fill(data, (byte) 80);
request.body(new String(data));
PolicyTestResponse response = send(request);
Assert.assertNotNull(response.body());
Assert.assertEquals("450", response.header("X-Bytes-Remaining"));
Assert.assertEquals("500", response.header("X-Bytes-Limit"));
send(request);
send(request);
send(request);
send(request);
// Now if we try it one more time, we'll get a failure!
try {
send(request);
Assert.fail("Expected a policy failure!");
} catch (PolicyFailureError e) {
PolicyFailure failure = e.getFailure();
Assert.assertEquals(PolicyFailureCodes.BYTE_QUOTA_EXCEEDED, failure.getFailureCode());
Assert.assertEquals("Transfer quota exceeded.", failure.getMessage());
Assert.assertEquals(429, failure.getResponseCode());
}
}
public static final class DownloadTestBackEndApi implements IPolicyTestBackEndApi {
/**
* @see io.apiman.test.policies.IPolicyTestBackEndApi#invoke(io.apiman.gateway.engine.beans.ApiRequest, byte[])
*/
@Override
public PolicyTestBackEndApiResponse invoke(ApiRequest request, byte[] requestBody) {
ApiResponse apiResponse = new ApiResponse();
apiResponse.setCode(200);
apiResponse.setMessage("OK"); //$NON-NLS-1$
apiResponse.getHeaders().put("Date", new Date().toString()); //$NON-NLS-1$
apiResponse.getHeaders().put("Server", "apiman.policy-test"); //$NON-NLS-1$ //$NON-NLS-2$
apiResponse.getHeaders().put("Content-Type", "text/plain"); //$NON-NLS-1$ //$NON-NLS-2$
int payloadSize = 20;
String payloadSizeHeader = request.getHeaders().get("X-Payload-Size");
if (payloadSizeHeader != null) {
payloadSize = new Integer(payloadSizeHeader);
}
byte [] payloadData = new byte[payloadSize];
Arrays.fill(payloadData, (byte) 80);
String payload = new String(payloadData);
PolicyTestBackEndApiResponse response = new PolicyTestBackEndApiResponse(apiResponse, payload);
return response;
}
}
}