Add Tests for EthernetNetworkFactory am: e78e8828d6
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/net/ethernet/+/1486182 Change-Id: If2049d3b4484d68232a9ce1b405aa438c9c673fa
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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 com.android.server.ethernet;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.LinkProperties;
|
||||||
|
import android.net.NetworkAgent;
|
||||||
|
import android.net.NetworkAgentConfig;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkProvider;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
|
||||||
|
public class EthernetNetworkAgent extends NetworkAgent {
|
||||||
|
|
||||||
|
private static final String TAG = "EthernetNetworkAgent";
|
||||||
|
|
||||||
|
public interface Callbacks {
|
||||||
|
void onNetworkUnwanted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Callbacks mCallbacks;
|
||||||
|
|
||||||
|
EthernetNetworkAgent(
|
||||||
|
@NonNull Context context,
|
||||||
|
@NonNull Looper looper,
|
||||||
|
@NonNull NetworkCapabilities nc,
|
||||||
|
@NonNull LinkProperties lp,
|
||||||
|
int networkScore,
|
||||||
|
@NonNull NetworkAgentConfig config,
|
||||||
|
@Nullable NetworkProvider provider,
|
||||||
|
@NonNull Callbacks cb) {
|
||||||
|
super(context, looper, TAG, nc, lp, networkScore, config, provider);
|
||||||
|
mCallbacks = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNetworkUnwanted() {
|
||||||
|
mCallbacks.onNetworkUnwanted();
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendLinkProperties is final in NetworkAgent, so it cannot be mocked.
|
||||||
|
public void sendLinkPropertiesImpl(LinkProperties lp) {
|
||||||
|
sendLinkProperties(lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Callbacks getCallbacks() {
|
||||||
|
return mCallbacks;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,10 +27,10 @@ import android.net.IpConfiguration;
|
|||||||
import android.net.IpConfiguration.IpAssignment;
|
import android.net.IpConfiguration.IpAssignment;
|
||||||
import android.net.IpConfiguration.ProxySettings;
|
import android.net.IpConfiguration.ProxySettings;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkAgent;
|
|
||||||
import android.net.NetworkAgentConfig;
|
import android.net.NetworkAgentConfig;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkFactory;
|
import android.net.NetworkFactory;
|
||||||
|
import android.net.NetworkProvider;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
import android.net.NetworkSpecifier;
|
import android.net.NetworkSpecifier;
|
||||||
import android.net.ip.IIpClient;
|
import android.net.ip.IIpClient;
|
||||||
@@ -40,12 +40,14 @@ import android.net.shared.ProvisioningConfiguration;
|
|||||||
import android.net.util.InterfaceParams;
|
import android.net.util.InterfaceParams;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AndroidRuntimeException;
|
import android.util.AndroidRuntimeException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
@@ -69,6 +71,25 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
final Dependencies mDeps;
|
||||||
|
|
||||||
|
public static class Dependencies {
|
||||||
|
public void makeIpClient(Context context, String iface, IpClientCallbacks callbacks) {
|
||||||
|
IpClientUtil.makeIpClient(context, iface, callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EthernetNetworkAgent makeEthernetNetworkAgent(Context context, Looper looper,
|
||||||
|
NetworkCapabilities nc, LinkProperties lp, int networkScore,
|
||||||
|
NetworkAgentConfig config, NetworkProvider provider,
|
||||||
|
EthernetNetworkAgent.Callbacks cb) {
|
||||||
|
return new EthernetNetworkAgent(context, looper, nc, lp, networkScore, config, provider,
|
||||||
|
cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterfaceParams getNetworkInterfaceByName(String name) {
|
||||||
|
return InterfaceParams.getByName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class ConfigurationException extends AndroidRuntimeException {
|
public static class ConfigurationException extends AndroidRuntimeException {
|
||||||
public ConfigurationException(String msg) {
|
public ConfigurationException(String msg) {
|
||||||
@@ -77,10 +98,17 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
|
public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
|
||||||
|
this(handler, context, filter, new Dependencies());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter,
|
||||||
|
Dependencies deps) {
|
||||||
super(handler.getLooper(), context, NETWORK_TYPE, filter);
|
super(handler.getLooper(), context, NETWORK_TYPE, filter);
|
||||||
|
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mDeps = deps;
|
||||||
|
|
||||||
setScoreFilter(NETWORK_SCORE);
|
setScoreFilter(NETWORK_SCORE);
|
||||||
}
|
}
|
||||||
@@ -149,7 +177,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterfaceState iface = new NetworkInterfaceState(
|
NetworkInterfaceState iface = new NetworkInterfaceState(
|
||||||
ifaceName, hwAddress, mHandler, mContext, capabilities, this);
|
ifaceName, hwAddress, mHandler, mContext, capabilities, this, mDeps);
|
||||||
iface.setIpConfig(ipConfiguration);
|
iface.setIpConfig(ipConfiguration);
|
||||||
mTrackingInterfaces.put(ifaceName, iface);
|
mTrackingInterfaces.put(ifaceName, iface);
|
||||||
|
|
||||||
@@ -251,6 +279,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final NetworkFactory mNetworkFactory;
|
private final NetworkFactory mNetworkFactory;
|
||||||
|
private final Dependencies mDeps;
|
||||||
private final int mLegacyType;
|
private final int mLegacyType;
|
||||||
|
|
||||||
private static String sTcpBufferSizes = null; // Lazy initialized.
|
private static String sTcpBufferSizes = null; // Lazy initialized.
|
||||||
@@ -260,7 +289,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
|
|
||||||
private volatile @Nullable IIpClient mIpClient;
|
private volatile @Nullable IIpClient mIpClient;
|
||||||
private @Nullable IpClientCallbacksImpl mIpClientCallback;
|
private @Nullable IpClientCallbacksImpl mIpClientCallback;
|
||||||
private @Nullable NetworkAgent mNetworkAgent;
|
private @Nullable EthernetNetworkAgent mNetworkAgent;
|
||||||
private @Nullable IpConfiguration mIpConfig;
|
private @Nullable IpConfiguration mIpConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,12 +389,14 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context,
|
NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context,
|
||||||
@NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory) {
|
@NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory,
|
||||||
|
Dependencies deps) {
|
||||||
name = ifaceName;
|
name = ifaceName;
|
||||||
mCapabilities = checkNotNull(capabilities);
|
mCapabilities = checkNotNull(capabilities);
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mNetworkFactory = networkFactory;
|
mNetworkFactory = networkFactory;
|
||||||
|
mDeps = deps;
|
||||||
int legacyType = ConnectivityManager.TYPE_NONE;
|
int legacyType = ConnectivityManager.TYPE_NONE;
|
||||||
int[] transportTypes = mCapabilities.getTransportTypes();
|
int[] transportTypes = mCapabilities.getTransportTypes();
|
||||||
|
|
||||||
@@ -451,7 +482,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mIpClientCallback = new IpClientCallbacksImpl();
|
mIpClientCallback = new IpClientCallbacksImpl();
|
||||||
IpClientUtil.makeIpClient(mContext, name, mIpClientCallback);
|
mDeps.makeIpClient(mContext, name, mIpClientCallback);
|
||||||
mIpClientCallback.awaitIpClientStart();
|
mIpClientCallback.awaitIpClientStart();
|
||||||
if (sTcpBufferSizes == null) {
|
if (sTcpBufferSizes == null) {
|
||||||
sTcpBufferSizes = mContext.getResources().getString(
|
sTcpBufferSizes = mContext.getResources().getString(
|
||||||
@@ -474,18 +505,19 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
.setLegacyTypeName(NETWORK_TYPE)
|
.setLegacyTypeName(NETWORK_TYPE)
|
||||||
.setLegacyExtraInfo(mHwAddress)
|
.setLegacyExtraInfo(mHwAddress)
|
||||||
.build();
|
.build();
|
||||||
mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(),
|
mNetworkAgent = mDeps.makeEthernetNetworkAgent(mContext, mHandler.getLooper(),
|
||||||
NETWORK_TYPE, mCapabilities, mLinkProperties,
|
mCapabilities, mLinkProperties, getNetworkScore(), config,
|
||||||
getNetworkScore(), config, mNetworkFactory.getProvider()) {
|
mNetworkFactory.getProvider(), new EthernetNetworkAgent.Callbacks() {
|
||||||
public void unwanted() {
|
@Override
|
||||||
if (this == mNetworkAgent) {
|
public void onNetworkUnwanted() {
|
||||||
stop();
|
if (this == mNetworkAgent.getCallbacks()) {
|
||||||
} else if (mNetworkAgent != null) {
|
stop();
|
||||||
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
|
} else if (mNetworkAgent != null) {
|
||||||
"instance");
|
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
|
||||||
} // Otherwise, we've already called stop.
|
"instance");
|
||||||
}
|
} // Otherwise, we've already called stop.
|
||||||
};
|
}
|
||||||
|
});
|
||||||
mNetworkAgent.register();
|
mNetworkAgent.register();
|
||||||
mNetworkAgent.markConnected();
|
mNetworkAgent.markConnected();
|
||||||
}
|
}
|
||||||
@@ -496,7 +528,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
stop();
|
stop();
|
||||||
// If the interface has disappeared provisioning will fail over and over again, so
|
// If the interface has disappeared provisioning will fail over and over again, so
|
||||||
// there is no point in starting again
|
// there is no point in starting again
|
||||||
if (null != InterfaceParams.getByName(name)) {
|
if (null != mDeps.getNetworkInterfaceByName(name)) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,7 +536,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
void updateLinkProperties(LinkProperties linkProperties) {
|
void updateLinkProperties(LinkProperties linkProperties) {
|
||||||
mLinkProperties = linkProperties;
|
mLinkProperties = linkProperties;
|
||||||
if (mNetworkAgent != null) {
|
if (mNetworkAgent != null) {
|
||||||
mNetworkAgent.sendLinkProperties(linkProperties);
|
mNetworkAgent.sendLinkPropertiesImpl(linkProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,7 +577,7 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
mLinkProperties);
|
mLinkProperties);
|
||||||
}
|
}
|
||||||
mNetworkAgent.sendNetworkCapabilities(mCapabilities);
|
mNetworkAgent.sendNetworkCapabilities(mCapabilities);
|
||||||
mNetworkAgent.sendLinkProperties(mLinkProperties);
|
mNetworkAgent.sendLinkPropertiesImpl(mLinkProperties);
|
||||||
|
|
||||||
// As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now
|
// As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now
|
||||||
// since the agent isn't updated frequently. Consider caching the score in the future if
|
// since the agent isn't updated frequently. Consider caching the score in the future if
|
||||||
|
|||||||
@@ -28,10 +28,14 @@ android_test {
|
|||||||
libs: [
|
libs: [
|
||||||
"android.test.runner",
|
"android.test.runner",
|
||||||
"android.test.base",
|
"android.test.base",
|
||||||
|
"android.test.mock",
|
||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"androidx.test.rules",
|
"androidx.test.rules",
|
||||||
"ethernet-service",
|
"ethernet-service",
|
||||||
|
"frameworks-base-testutils",
|
||||||
|
"mockito-target-minus-junit4",
|
||||||
|
"services.net",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.android.server.ethernet.tests">
|
package="com.android.server.ethernet.tests">
|
||||||
|
|
||||||
<application android:label="EthernetServiceTests">
|
<application>
|
||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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 com.android.server.ethernet;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.app.test.MockAnswerUtil.AnswerWithArguments;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.net.EthernetNetworkSpecifier;
|
||||||
|
import android.net.IpConfiguration;
|
||||||
|
import android.net.LinkProperties;
|
||||||
|
import android.net.NetworkAgentConfig;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkProvider;
|
||||||
|
import android.net.NetworkRequest;
|
||||||
|
import android.net.ip.IIpClient;
|
||||||
|
import android.net.ip.IpClientCallbacks;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.test.TestLooper;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class EthernetNetworkFactoryTest {
|
||||||
|
private TestLooper mLooper = new TestLooper();
|
||||||
|
private Handler mHandler;
|
||||||
|
private EthernetNetworkFactory mNetFactory = null;
|
||||||
|
private IpClientCallbacks mIpClientCallbacks;
|
||||||
|
private int mNetworkRequestCount = 0;
|
||||||
|
@Mock private Context mContext;
|
||||||
|
@Mock private Resources mResources;
|
||||||
|
@Mock private EthernetNetworkFactory.Dependencies mDeps;
|
||||||
|
@Mock private IIpClient mIpClient;
|
||||||
|
@Mock private EthernetNetworkAgent mNetworkAgent;
|
||||||
|
@Mock private InterfaceParams mInterfaceParams;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mHandler = new Handler(mLooper.getLooper());
|
||||||
|
mNetworkRequestCount = 0;
|
||||||
|
|
||||||
|
mNetFactory = new EthernetNetworkFactory(mHandler, mContext, createDefaultFilterCaps(),
|
||||||
|
mDeps);
|
||||||
|
|
||||||
|
setupNetworkAgentMock();
|
||||||
|
setupIpClientMock();
|
||||||
|
setupContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupNetworkAgentMock() {
|
||||||
|
when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(),
|
||||||
|
any())).thenAnswer(new AnswerWithArguments() {
|
||||||
|
public EthernetNetworkAgent answer(
|
||||||
|
Context context,
|
||||||
|
Looper looper,
|
||||||
|
NetworkCapabilities nc,
|
||||||
|
LinkProperties lp,
|
||||||
|
int networkScore,
|
||||||
|
NetworkAgentConfig config,
|
||||||
|
NetworkProvider provider,
|
||||||
|
EthernetNetworkAgent.Callbacks cb) {
|
||||||
|
when(mNetworkAgent.getCallbacks()).thenReturn(cb);
|
||||||
|
return mNetworkAgent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupIpClientMock() throws Exception {
|
||||||
|
doAnswer(inv -> {
|
||||||
|
// these tests only support one concurrent IpClient, so make sure we do not accidentally
|
||||||
|
// create a mess.
|
||||||
|
assertNull("An IpClient has already been created.", mIpClientCallbacks);
|
||||||
|
|
||||||
|
mIpClientCallbacks = inv.getArgument(2);
|
||||||
|
mIpClientCallbacks.onIpClientCreated(mIpClient);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
return null;
|
||||||
|
}).when(mDeps).makeIpClient(any(Context.class), anyString(), any());
|
||||||
|
|
||||||
|
doAnswer(inv -> {
|
||||||
|
mIpClientCallbacks.onQuit();
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
mIpClientCallbacks = null;
|
||||||
|
return null;
|
||||||
|
}).when(mIpClient).shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupContext() {
|
||||||
|
when(mContext.getResources()).thenReturn(mResources);
|
||||||
|
when(mResources.getString(R.string.config_ethernet_tcp_buffers)).thenReturn(
|
||||||
|
"524288,1048576,3145728,524288,1048576,2097152");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
// looper is shared with the network agents, so there may still be messages to dispatch on
|
||||||
|
// tear down.
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkCapabilities createDefaultFilterCaps() {
|
||||||
|
return NetworkCapabilities.Builder.withoutDefaultCapabilities()
|
||||||
|
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkCapabilities.Builder createInterfaceCapsBuilder() {
|
||||||
|
return new NetworkCapabilities.Builder()
|
||||||
|
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkRequest.Builder createDefaultRequestBuilder() {
|
||||||
|
return new NetworkRequest.Builder()
|
||||||
|
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NetworkRequest createDefaultRequest() {
|
||||||
|
return createDefaultRequestBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IpConfiguration createDefaultIpConfig() {
|
||||||
|
IpConfiguration ipConfig = new IpConfiguration();
|
||||||
|
ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
|
||||||
|
ipConfig.setProxySettings(IpConfiguration.ProxySettings.NONE);
|
||||||
|
return ipConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates an interface with provisioning in progress (since updating the interface link state
|
||||||
|
// automatically starts the provisioning process)
|
||||||
|
private void createInterfaceUndergoingProvisioning(String iface) throws Exception {
|
||||||
|
mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder().build(),
|
||||||
|
createDefaultIpConfig());
|
||||||
|
assertTrue(mNetFactory.updateInterfaceLinkState(iface, true));
|
||||||
|
verify(mDeps).makeIpClient(any(Context.class), anyString(), any());
|
||||||
|
verify(mIpClient).startProvisioning(any());
|
||||||
|
clearInvocations(mDeps);
|
||||||
|
clearInvocations(mIpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a provisioned interface
|
||||||
|
private void createProvisionedInterface(String iface) throws Exception {
|
||||||
|
createInterfaceUndergoingProvisioning(iface);
|
||||||
|
mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
// provisioning succeeded, verify that the network agent is created, registered, and marked
|
||||||
|
// as connected.
|
||||||
|
verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(),
|
||||||
|
any());
|
||||||
|
verify(mNetworkAgent).register();
|
||||||
|
verify(mNetworkAgent).markConnected();
|
||||||
|
clearInvocations(mDeps);
|
||||||
|
clearInvocations(mNetworkAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates an unprovisioned interface
|
||||||
|
private void createUnprovisionedInterface(String iface) throws Exception {
|
||||||
|
// the only way to create an unprovisioned interface is by calling needNetworkFor
|
||||||
|
// followed by releaseNetworkFor which will stop the NetworkAgent and IpClient. When
|
||||||
|
// EthernetNetworkFactory#updateInterfaceLinkState(iface, true) is called, the interface
|
||||||
|
// is automatically provisioned even if nobody has ever called needNetworkFor
|
||||||
|
createProvisionedInterface(iface);
|
||||||
|
|
||||||
|
// Interface is already provisioned, so startProvisioning / register should not be called
|
||||||
|
// again
|
||||||
|
mNetFactory.needNetworkFor(createDefaultRequest());
|
||||||
|
verify(mIpClient, never()).startProvisioning(any());
|
||||||
|
verify(mNetworkAgent, never()).register();
|
||||||
|
|
||||||
|
mNetFactory.releaseNetworkFor(createDefaultRequest());
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
verify(mNetworkAgent).unregister();
|
||||||
|
|
||||||
|
clearInvocations(mIpClient);
|
||||||
|
clearInvocations(mNetworkAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAcceptRequest() throws Exception {
|
||||||
|
createInterfaceUndergoingProvisioning("eth0");
|
||||||
|
assertTrue(mNetFactory.acceptRequest(createDefaultRequest()));
|
||||||
|
|
||||||
|
NetworkRequest wifiRequest = createDefaultRequestBuilder()
|
||||||
|
.removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||||
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
|
||||||
|
assertFalse(mNetFactory.acceptRequest(wifiRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
createInterfaceUndergoingProvisioning(iface);
|
||||||
|
// verify that the IpClient gets shut down when interface state changes to down.
|
||||||
|
assertTrue(mNetFactory.updateInterfaceLinkState(iface, false));
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
createProvisionedInterface(iface);
|
||||||
|
assertTrue(mNetFactory.updateInterfaceLinkState(iface, false));
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
verify(mNetworkAgent).unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
createUnprovisionedInterface(iface);
|
||||||
|
assertTrue(mNetFactory.updateInterfaceLinkState(iface, false));
|
||||||
|
// There should not be an active IPClient or NetworkAgent.
|
||||||
|
verify(mDeps, never()).makeIpClient(any(), any(), any());
|
||||||
|
verify(mDeps, never()).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(),
|
||||||
|
any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception {
|
||||||
|
// if interface was never added, link state cannot be updated.
|
||||||
|
assertFalse(mNetFactory.updateInterfaceLinkState("eth1", true));
|
||||||
|
verify(mDeps, never()).makeIpClient(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeedNetworkForOnProvisionedInterface() throws Exception {
|
||||||
|
createProvisionedInterface("eth0");
|
||||||
|
mNetFactory.needNetworkFor(createDefaultRequest());
|
||||||
|
verify(mIpClient, never()).startProvisioning(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeedNetworkForOnUnprovisionedInterface() throws Exception {
|
||||||
|
createUnprovisionedInterface("eth0");
|
||||||
|
mNetFactory.needNetworkFor(createDefaultRequest());
|
||||||
|
verify(mIpClient).startProvisioning(any());
|
||||||
|
|
||||||
|
mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mNetworkAgent).register();
|
||||||
|
verify(mNetworkAgent).markConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception {
|
||||||
|
createInterfaceUndergoingProvisioning("eth0");
|
||||||
|
mNetFactory.needNetworkFor(createDefaultRequest());
|
||||||
|
verify(mIpClient, never()).startProvisioning(any());
|
||||||
|
|
||||||
|
mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mNetworkAgent).register();
|
||||||
|
verify(mNetworkAgent).markConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProvisioningLoss() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams);
|
||||||
|
createProvisionedInterface(iface);
|
||||||
|
|
||||||
|
mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
verify(mNetworkAgent).unregister();
|
||||||
|
// provisioning loss should trigger a retry, since the interface is still there
|
||||||
|
verify(mIpClient).startProvisioning(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProvisioningLossForDisappearedInterface() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
// mocked method returns null by default, but just to be explicit in the test:
|
||||||
|
when(mDeps.getNetworkInterfaceByName(eq(iface))).thenReturn(null);
|
||||||
|
|
||||||
|
createProvisionedInterface(iface);
|
||||||
|
mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
verify(mNetworkAgent).unregister();
|
||||||
|
// the interface disappeared and getNetworkInterfaceByName returns null, we should not retry
|
||||||
|
verify(mIpClient, never()).startProvisioning(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
createUnprovisionedInterface(iface);
|
||||||
|
mNetFactory.updateInterfaceLinkState(iface, false);
|
||||||
|
|
||||||
|
mNetFactory.needNetworkFor(createDefaultRequest());
|
||||||
|
|
||||||
|
NetworkRequest specificNetRequest = new NetworkRequest.Builder()
|
||||||
|
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||||
|
.setNetworkSpecifier(new EthernetNetworkSpecifier(iface))
|
||||||
|
.build();
|
||||||
|
mNetFactory.needNetworkFor(specificNetRequest);
|
||||||
|
|
||||||
|
// TODO(b/155707957): BUG: IPClient should not be started when the interface link state
|
||||||
|
// is down.
|
||||||
|
verify(mDeps).makeIpClient(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLinkPropertiesChanged() throws Exception {
|
||||||
|
createProvisionedInterface("eth0");
|
||||||
|
|
||||||
|
LinkProperties lp = new LinkProperties();
|
||||||
|
mIpClientCallbacks.onLinkPropertiesChange(lp);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mNetworkAgent).sendLinkPropertiesImpl(same(lp));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkUnwanted() throws Exception {
|
||||||
|
createProvisionedInterface("eth0");
|
||||||
|
|
||||||
|
mNetworkAgent.getCallbacks().onNetworkUnwanted();
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mIpClient).shutdown();
|
||||||
|
verify(mNetworkAgent).unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception {
|
||||||
|
String iface = "eth0";
|
||||||
|
// ensures provisioning is restarted after provisioning loss
|
||||||
|
when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams);
|
||||||
|
createProvisionedInterface(iface);
|
||||||
|
|
||||||
|
EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks();
|
||||||
|
// replace network agent in EthernetNetworkFactory
|
||||||
|
// Loss of provisioning will restart the ip client and network agent.
|
||||||
|
mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mDeps).makeIpClient(any(), any(), any());
|
||||||
|
|
||||||
|
mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(),
|
||||||
|
any());
|
||||||
|
|
||||||
|
// verify that unwanted is ignored
|
||||||
|
clearInvocations(mIpClient);
|
||||||
|
clearInvocations(mNetworkAgent);
|
||||||
|
oldCbs.onNetworkUnwanted();
|
||||||
|
verify(mIpClient, never()).shutdown();
|
||||||
|
verify(mNetworkAgent, never()).unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user