Merge "Add more test coverage for UrlRequest and ConnectionMigrationOptions."

This commit is contained in:
Dan Stahr
2023-03-10 18:12:35 +00:00
committed by Gerrit Code Review
3 changed files with 249 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ package android.net.http.cts
import android.net.http.ConnectionMigrationOptions import android.net.http.ConnectionMigrationOptions
import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED
import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_UNSPECIFIED
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -26,6 +27,16 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class ConnectionMigrationOptionsTest { class ConnectionMigrationOptionsTest {
@Test
fun testConnectionMigrationOptions_defaultValues() {
val options =
ConnectionMigrationOptions.Builder().build()
assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.allowNonDefaultNetworkUsageEnabled)
assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.defaultNetworkMigrationEnabled)
assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.pathDegradationMigrationEnabled)
}
@Test @Test
fun testConnectionMigrationOptions_enableDefaultNetworkMigration_returnSetValue() { fun testConnectionMigrationOptions_enableDefaultNetworkMigration_returnSetValue() {
val options = val options =
@@ -45,4 +56,13 @@ class ConnectionMigrationOptionsTest {
assertEquals(MIGRATION_OPTION_ENABLED, options.pathDegradationMigrationEnabled) assertEquals(MIGRATION_OPTION_ENABLED, options.pathDegradationMigrationEnabled)
} }
@Test
fun testConnectionMigrationOptions_allowNonDefaultNetworkUsage_returnSetValue() {
val options =
ConnectionMigrationOptions.Builder()
.setAllowNonDefaultNetworkUsageEnabled(MIGRATION_OPTION_ENABLED).build()
assertEquals(MIGRATION_OPTION_ENABLED, options.allowNonDefaultNetworkUsageEnabled)
}
} }

View File

@@ -19,6 +19,8 @@ package android.net.http.cts;
import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode; import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode;
import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection; import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection;
import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -40,15 +42,19 @@ import android.net.http.cts.util.TestStatusListener;
import android.net.http.cts.util.TestUploadDataProvider; import android.net.http.cts.util.TestUploadDataProvider;
import android.net.http.cts.util.TestUrlRequestCallback; import android.net.http.cts.util.TestUrlRequestCallback;
import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep; import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
import android.net.http.cts.util.UploadDataProviders;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.base.Strings;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.net.URLEncoder;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@@ -279,6 +285,31 @@ public class UrlRequestTest {
assertTrue(e.getCause().getMessage().contains("full")); assertTrue(e.getCause().getMessage().contains("full"));
} }
@Test
public void testUrlRequestPost_withRedirect() throws Exception {
String body = Strings.repeat(
"Hello, this is a really interesting body, so write this 100 times.", 100);
String redirectUrlParameter =
URLEncoder.encode(mTestServer.getEchoBodyUrl(), "UTF-8");
createUrlRequestBuilder(
String.format(
"%s/alt_redirect?dest=%s&statusCode=307",
mTestServer.getBaseUri(),
redirectUrlParameter))
.setHttpMethod("POST")
.addHeader("Content-Type", "text/plain")
.setUploadDataProvider(
UploadDataProviders.create(body.getBytes(StandardCharsets.UTF_8)),
mCallback.getExecutor())
.build()
.start();
mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
assertOKStatusCode(mCallback.mResponseInfo);
assertThat(mCallback.mResponseAsString).isEqualTo(body);
}
private static class StubUrlRequestCallback extends UrlRequest.Callback { private static class StubUrlRequestCallback extends UrlRequest.Callback {
@Override @Override

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* 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 android.net.http.cts.util;
import android.net.http.UploadDataProvider;
import android.net.http.UploadDataSink;
import android.os.ParcelFileDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* Provides implementations of {@link UploadDataProvider} for common use cases. Corresponds to
* {@code android.net.http.apihelpers.UploadDataProviders} which is not an exposed API.
*/
public final class UploadDataProviders {
/**
* Uploads an entire file.
*
* @param file The file to upload
* @return A new UploadDataProvider for the given file
*/
public static UploadDataProvider create(final File file) {
return new FileUploadProvider(() -> new FileInputStream(file).getChannel());
}
/**
* Uploads an entire file, closing the descriptor when it is no longer needed.
*
* @param fd The file descriptor to upload
* @throws IllegalArgumentException if {@code fd} is not a file.
* @return A new UploadDataProvider for the given file descriptor
*/
public static UploadDataProvider create(final ParcelFileDescriptor fd) {
return new FileUploadProvider(() -> {
if (fd.getStatSize() != -1) {
return new ParcelFileDescriptor.AutoCloseInputStream(fd).getChannel();
} else {
fd.close();
throw new IllegalArgumentException("Not a file: " + fd);
}
});
}
/**
* Uploads a ByteBuffer, from the current {@code buffer.position()} to {@code buffer.limit()}
*
* @param buffer The data to upload
* @return A new UploadDataProvider for the given buffer
*/
public static UploadDataProvider create(ByteBuffer buffer) {
return new ByteBufferUploadProvider(buffer.slice());
}
/**
* Uploads {@code length} bytes from {@code data}, starting from {@code offset}
*
* @param data Array containing data to upload
* @param offset Offset within data to start with
* @param length Number of bytes to upload
* @return A new UploadDataProvider for the given data
*/
public static UploadDataProvider create(byte[] data, int offset, int length) {
return new ByteBufferUploadProvider(ByteBuffer.wrap(data, offset, length).slice());
}
/**
* Uploads the contents of {@code data}
*
* @param data Array containing data to upload
* @return A new UploadDataProvider for the given data
*/
public static UploadDataProvider create(byte[] data) {
return create(data, 0, data.length);
}
private interface FileChannelProvider {
FileChannel getChannel() throws IOException;
}
private static final class FileUploadProvider extends UploadDataProvider {
private volatile FileChannel mChannel;
private final FileChannelProvider mProvider;
/** Guards initialization of {@code mChannel} */
private final Object mLock = new Object();
private FileUploadProvider(FileChannelProvider provider) {
this.mProvider = provider;
}
@Override
public long getLength() throws IOException {
return getChannel().size();
}
@Override
public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IOException {
if (!byteBuffer.hasRemaining()) {
throw new IllegalStateException("Cronet passed a buffer with no bytes remaining");
}
FileChannel channel = getChannel();
int bytesRead = 0;
while (bytesRead == 0) {
int read = channel.read(byteBuffer);
if (read == -1) {
break;
} else {
bytesRead += read;
}
}
uploadDataSink.onReadSucceeded(false);
}
@Override
public void rewind(UploadDataSink uploadDataSink) throws IOException {
getChannel().position(0);
uploadDataSink.onRewindSucceeded();
}
/**
* Lazily initializes the channel so that a blocking operation isn't performed
* on a non-executor thread.
*/
private FileChannel getChannel() throws IOException {
if (mChannel == null) {
synchronized (mLock) {
if (mChannel == null) {
mChannel = mProvider.getChannel();
}
}
}
return mChannel;
}
@Override
public void close() throws IOException {
FileChannel channel = mChannel;
if (channel != null) {
channel.close();
}
}
}
private static final class ByteBufferUploadProvider extends UploadDataProvider {
private final ByteBuffer mUploadBuffer;
private ByteBufferUploadProvider(ByteBuffer uploadBuffer) {
this.mUploadBuffer = uploadBuffer;
}
@Override
public long getLength() {
return mUploadBuffer.limit();
}
@Override
public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) {
if (!byteBuffer.hasRemaining()) {
throw new IllegalStateException("Cronet passed a buffer with no bytes remaining");
}
if (byteBuffer.remaining() >= mUploadBuffer.remaining()) {
byteBuffer.put(mUploadBuffer);
} else {
int oldLimit = mUploadBuffer.limit();
mUploadBuffer.limit(mUploadBuffer.position() + byteBuffer.remaining());
byteBuffer.put(mUploadBuffer);
mUploadBuffer.limit(oldLimit);
}
uploadDataSink.onReadSucceeded(false);
}
@Override
public void rewind(UploadDataSink uploadDataSink) {
mUploadBuffer.position(0);
uploadDataSink.onRewindSucceeded();
}
}
// Prevent instantiation
private UploadDataProviders() {}
}