Merge changes Id2a6bfdf,I5cab2b78
* changes: Remove qtaguid support in NetworkStatsFactory Refactor NetworkStatsFactoryTest
This commit is contained in:
@@ -33,23 +33,26 @@ import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.TrafficStats;
|
||||
import android.net.UnderlyingNetworkInfo;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.frameworks.tests.net.R;
|
||||
import com.android.internal.util.ProcFileReader;
|
||||
import com.android.server.BpfNetMaps;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.io.Streams;
|
||||
import libcore.testing.io.TestIoUtils;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -60,10 +63,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
|
||||
/** Tests for {@link NetworkStatsFactory}. */
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@@ -75,6 +76,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
private File mTestProc;
|
||||
private NetworkStatsFactory mFactory;
|
||||
@Mock private Context mContext;
|
||||
@Mock private NetworkStatsFactory.Dependencies mDeps;
|
||||
@Mock private BpfNetMaps mBpfNetMaps;
|
||||
|
||||
@Before
|
||||
@@ -86,7 +88,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// applications. So in order to have a test support native library, the native code
|
||||
// related to networkStatsFactory is compiled to a minimal native library and loaded here.
|
||||
System.loadLibrary("networkstatsfactorytestjni");
|
||||
mFactory = new NetworkStatsFactory(mContext, mTestProc, false, mBpfNetMaps);
|
||||
doReturn(mBpfNetMaps).when(mDeps).createBpfNetMaps(any());
|
||||
mFactory = new NetworkStatsFactory(mContext, mDeps);
|
||||
mFactory.updateUnderlyingNetworkInfos(new UnderlyingNetworkInfo[0]);
|
||||
}
|
||||
|
||||
@@ -97,7 +100,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
|
||||
@Test
|
||||
public void testNetworkStatsDetail() throws Exception {
|
||||
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
|
||||
final NetworkStats stats = factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_typical);
|
||||
|
||||
assertEquals(70, stats.size());
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 18621L, 2898L);
|
||||
@@ -122,8 +125,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// over VPN.
|
||||
//
|
||||
// VPN UID rewrites packets read from TUN back to TUN, plus some of its own traffic
|
||||
|
||||
final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_rewrite_through_self);
|
||||
final NetworkStats tunStats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_rewrite_through_self);
|
||||
|
||||
assertValues(tunStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
|
||||
DEFAULT_NETWORK_ALL, 2000L, 200L, 1000L, 100L, 0);
|
||||
@@ -164,7 +167,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// UID_RED: 2000 bytes, 200 packets
|
||||
// UID_BLUE: 1000 bytes, 100 packets
|
||||
// UID_VPN: 6300 bytes, 0 packets
|
||||
final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_with_clat);
|
||||
final NetworkStats tunStats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_with_clat);
|
||||
|
||||
assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_RED, 2000L, 200L, 1000, 100L);
|
||||
assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
|
||||
@@ -188,7 +192,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// attributed to UID_BLUE, and 150 bytes attributed to UID_VPN.
|
||||
// Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
|
||||
// attributed to UID_BLUE, and 300 bytes attributed to UID_VPN.
|
||||
final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying);
|
||||
final NetworkStats tunStats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_one_underlying);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
|
||||
@@ -217,7 +222,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// Of 8800 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
|
||||
// attributed to UID_BLUE, and 5800 bytes attributed to UID_VPN.
|
||||
final NetworkStats tunStats =
|
||||
parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_own_traffic);
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_one_underlying_own_traffic);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
|
||||
@@ -239,7 +244,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// Of 1000 bytes over WiFi, expect 250 bytes attributed UID_RED and 750 bytes to UID_BLUE,
|
||||
// with nothing attributed to UID_VPN for both rx/tx traffic.
|
||||
final NetworkStats tunStats =
|
||||
parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_compression);
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_one_underlying_compression);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 250L, 25L, 250L, 25L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_BLUE, 750L, 75L, 750L, 75L);
|
||||
@@ -263,7 +268,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE.
|
||||
// - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID.
|
||||
final NetworkStats tunStats =
|
||||
parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_duplication);
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_two_underlying_duplication);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 500L, 50L, 500L, 50L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_BLUE, 500L, 50L, 500L, 50L);
|
||||
@@ -303,7 +308,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes
|
||||
// attributed to UID_BLUE, and 350 bytes attributed to UID_VPN.
|
||||
final NetworkStats tunStats =
|
||||
parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn);
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
|
||||
@@ -333,7 +338,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
//
|
||||
// For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for tx traffic.
|
||||
// And, 30 bytes over WiFi and 20 bytes over Cell for rx traffic.
|
||||
final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split);
|
||||
final NetworkStats tunStats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_two_underlying_split);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 300L, 30L, 600L, 60L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_VPN, 30L, 0L, 60L, 0L);
|
||||
@@ -357,7 +363,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// rx/tx.
|
||||
// UID_VPN gets nothing attributed to it (avoiding negative stats).
|
||||
final NetworkStats tunStats =
|
||||
parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split_compression);
|
||||
factoryReadNetworkStatsDetail(
|
||||
R.raw.xt_qtaguid_vpn_two_underlying_split_compression);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 600L, 60L, 600L, 60L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L);
|
||||
@@ -378,7 +385,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
|
||||
// VPN sent/received 1100 bytes (100 packets) over Cell.
|
||||
// Of 1100 bytes over Cell, expect all of it attributed to UID_VPN for both rx/tx traffic.
|
||||
final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_incorrect_iface);
|
||||
final NetworkStats tunStats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_vpn_incorrect_iface);
|
||||
|
||||
assertValues(tunStats, TEST_IFACE, UID_RED, 0L, 0L, 0L, 0L);
|
||||
assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L);
|
||||
@@ -403,36 +411,15 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
|
||||
@Test
|
||||
public void testNetworkStatsWithSet() throws Exception {
|
||||
final NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_typical);
|
||||
final NetworkStats stats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_typical);
|
||||
|
||||
assertEquals(70, stats.size());
|
||||
assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L,
|
||||
676L);
|
||||
assertStatsEntry(stats, "rmnet1", 10021, SET_FOREGROUND, 0x30100000, 742L, 3L, 1265L, 3L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetworkStatsSingle() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsSummaryDev();
|
||||
assertEquals(6, stats.size());
|
||||
assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 2112L, 24L, 700L, 10L);
|
||||
assertStatsEntry(stats, "test1", UID_ALL, SET_ALL, TAG_NONE, 6L, 8L, 10L, 12L);
|
||||
assertStatsEntry(stats, "test2", UID_ALL, SET_ALL, TAG_NONE, 1L, 2L, 3L, 4L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetworkStatsXt() throws Exception {
|
||||
stageFile(R.raw.xt_qtaguid_iface_fmt_typical, file("net/xt_qtaguid/iface_stat_fmt"));
|
||||
|
||||
final NetworkStats stats = mFactory.readNetworkStatsSummaryXt();
|
||||
assertEquals(3, stats.size());
|
||||
assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 6824L, 16L, 5692L, 10L);
|
||||
assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L,
|
||||
2468L);
|
||||
assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleClatAccountingSimple() throws Exception {
|
||||
mFactory.noteStackedIface("v4-wlan0", "wlan0");
|
||||
@@ -441,7 +428,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
// - 213 received 464xlat packets of size 200 bytes
|
||||
// - 41 sent 464xlat packets of size 100 bytes
|
||||
// - no other traffic on base interface for root uid.
|
||||
NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_simple);
|
||||
final NetworkStats stats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_with_clat_simple);
|
||||
assertEquals(3, stats.size());
|
||||
|
||||
assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 46860L, 4920L);
|
||||
@@ -452,7 +440,8 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
public void testDoubleClatAccounting() throws Exception {
|
||||
mFactory.noteStackedIface("v4-wlan0", "wlan0");
|
||||
|
||||
NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat);
|
||||
final NetworkStats stats =
|
||||
factoryReadNetworkStatsDetail(R.raw.xt_qtaguid_with_clat);
|
||||
assertEquals(42, stats.size());
|
||||
|
||||
assertStatsEntry(stats, "v4-wlan0", 0, SET_DEFAULT, 0x0, 356L, 276L);
|
||||
@@ -473,65 +462,78 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
|
||||
assertNoStatsEntry(stats, "wlan0", 1029, SET_DEFAULT, 0x0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleClatAccounting100MBDownload() throws Exception {
|
||||
// Downloading 100mb from an ipv4 only destination in a foreground activity
|
||||
|
||||
long appRxBytesBefore = 328684029L;
|
||||
long appRxBytesAfter = 439237478L;
|
||||
assertEquals("App traffic should be ~100MB", 110553449, appRxBytesAfter - appRxBytesBefore);
|
||||
|
||||
long rootRxBytes = 330187296L;
|
||||
|
||||
mFactory.noteStackedIface("v4-wlan0", "wlan0");
|
||||
NetworkStats stats;
|
||||
|
||||
// Stats snapshot before the download
|
||||
stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_before);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesBefore, 5199872L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L);
|
||||
|
||||
// Stats snapshot after the download
|
||||
stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_after);
|
||||
assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
|
||||
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a {@link Resources#openRawResource(int)} into {@link File} for
|
||||
* testing purposes.
|
||||
*/
|
||||
private void stageFile(int rawId, File file) throws Exception {
|
||||
new File(file.getParent()).mkdirs();
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
private NetworkStats parseNetworkStatsFromGoldenSample(int resourceId, int initialSize,
|
||||
boolean consumeHeader, boolean checkActive, boolean isUidData) throws IOException {
|
||||
final NetworkStats stats =
|
||||
new NetworkStats(SystemClock.elapsedRealtime(), initialSize);
|
||||
final NetworkStats.Entry entry = new NetworkStats.Entry();
|
||||
ProcFileReader reader = null;
|
||||
int idx = 1;
|
||||
int lastIdx = 1;
|
||||
try {
|
||||
in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
|
||||
out = new FileOutputStream(file);
|
||||
Streams.copy(in, out);
|
||||
reader = new ProcFileReader(InstrumentationRegistry.getContext().getResources()
|
||||
.openRawResource(resourceId));
|
||||
|
||||
if (consumeHeader) {
|
||||
reader.finishLine();
|
||||
}
|
||||
|
||||
while (reader.hasMoreData()) {
|
||||
if (isUidData) {
|
||||
idx = reader.nextInt();
|
||||
if (idx != lastIdx + 1) {
|
||||
throw new ProtocolException(
|
||||
"inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
|
||||
}
|
||||
lastIdx = idx;
|
||||
}
|
||||
|
||||
entry.iface = reader.nextString();
|
||||
// Read the uid based information from file. Otherwise, assign with target value.
|
||||
entry.tag = isUidData ? kernelToTag(reader.nextString()) : TAG_NONE;
|
||||
entry.uid = isUidData ? reader.nextInt() : UID_ALL;
|
||||
entry.set = isUidData ? reader.nextInt() : SET_ALL;
|
||||
|
||||
// For fetching active numbers. Dev specific
|
||||
final boolean active = checkActive ? reader.nextInt() != 0 : false;
|
||||
|
||||
// Always include snapshot values
|
||||
entry.rxBytes = reader.nextLong();
|
||||
entry.rxPackets = reader.nextLong();
|
||||
entry.txBytes = reader.nextLong();
|
||||
entry.txPackets = reader.nextLong();
|
||||
|
||||
// Fold in active numbers, but only when active
|
||||
if (active) {
|
||||
entry.rxBytes += reader.nextLong();
|
||||
entry.rxPackets += reader.nextLong();
|
||||
entry.txBytes += reader.nextLong();
|
||||
entry.txPackets += reader.nextLong();
|
||||
}
|
||||
|
||||
stats.insertEntry(entry);
|
||||
reader.finishLine();
|
||||
}
|
||||
} catch (NullPointerException | NumberFormatException e) {
|
||||
final String errMsg = isUidData
|
||||
? "problem parsing idx " + idx : "problem parsing stats";
|
||||
final ProtocolException pe = new ProtocolException(errMsg);
|
||||
pe.initCause(e);
|
||||
throw pe;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(in);
|
||||
IoUtils.closeQuietly(out);
|
||||
IoUtils.closeQuietly(reader);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
private void stageLong(long value, File file) throws Exception {
|
||||
new File(file.getParent()).mkdirs();
|
||||
FileWriter out = null;
|
||||
try {
|
||||
out = new FileWriter(file);
|
||||
out.write(Long.toString(value));
|
||||
} finally {
|
||||
IoUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
private File file(String path) throws Exception {
|
||||
return new File(mTestProc, path);
|
||||
}
|
||||
|
||||
private NetworkStats parseDetailedStats(int resourceId) throws Exception {
|
||||
stageFile(resourceId, file("net/xt_qtaguid/stats"));
|
||||
private NetworkStats factoryReadNetworkStatsDetail(int resourceId) throws Exception {
|
||||
// Choose a general detail stats sample size from the experiences to prevent from
|
||||
// frequently allocating buckets.
|
||||
final NetworkStats statsFromResource = parseNetworkStatsFromGoldenSample(resourceId,
|
||||
24 /* initialSize */, true /* consumeHeader */, false /* checkActive */,
|
||||
true /* isUidData */);
|
||||
doReturn(statsFromResource).when(mDeps).getNetworkStatsDetail(anyInt(), any(),
|
||||
anyInt());
|
||||
return mFactory.readNetworkStatsDetail();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user