diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index d819b9642e..66ca4b6b7e 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -57,7 +57,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aType(IpReachabilityEvent.class), anInt(IpReachabilityEvent.NUD_FAILED)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -70,13 +70,13 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.netId = 123; ev.transports = 3; // transports have priority for inferrence of link layer ev.ifname = "wlan0"; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -89,12 +89,12 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.transports = 1; ev.ifname = null; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -107,12 +107,12 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.transports = 0; ev.ifname = "not_inferred"; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"not_inferred\"", @@ -125,11 +125,11 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.ifname = "bt-pan"; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -142,11 +142,11 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.ifname = "rmnet_ipa0"; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -159,11 +159,11 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); ev.ifname = "wlan0"; - want = joinLines( + want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -176,7 +176,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -190,7 +190,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aBool(true), aBool(false)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -211,7 +211,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " transport_types: 3", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -223,7 +223,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aString("SomeState"), anInt(192)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -237,7 +237,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"SomeState\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -248,7 +248,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aType(DhcpErrorEvent.class), anInt(DhcpErrorEvent.L4_NOT_UDP)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -262,59 +262,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " error_code: 50397184", " >", ">", - "version: 2"); - - verifySerialization(want, ev); - } - - @SmallTest - public void testDnsEventSerialization() { - ConnectivityMetricsEvent ev = describeIpEvent( - aType(DnsEvent.class), - anInt(101), - aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)), - aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)), - anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300)); - - String want = joinLines( - "dropped_events: 0", - "events <", - " if_name: \"\"", - " link_layer: 0", - " network_id: 0", - " time_ms: 1", - " transports: 0", - " dns_lookup_batch <", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " event_types: 1", - " event_types: 1", - " event_types: 1", - " event_types: 2", - " event_types: 2", - " latencies_ms: 3456", - " latencies_ms: 267", - " latencies_ms: 1230", - " latencies_ms: 45", - " latencies_ms: 2111", - " latencies_ms: 450", - " latencies_ms: 638", - " latencies_ms: 1300", - " network_id <", - " network_id: 101", - " >", - " return_codes: 0", - " return_codes: 0", - " return_codes: 22", - " return_codes: 3", - " return_codes: 1", - " return_codes: 0", - " return_codes: 200", - " return_codes: 178", - " >", - ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -326,7 +274,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(IpManagerEvent.PROVISIONING_OK), aLong(5678)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -340,7 +288,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " latency_ms: 5678", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -351,7 +299,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aType(IpReachabilityEvent.class), anInt(IpReachabilityEvent.NUD_FAILED)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -364,7 +312,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -377,7 +325,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(5), aLong(20410)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -393,7 +341,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " >", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -406,7 +354,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(ValidationProbeEvent.PROBE_HTTP), anInt(204)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -420,7 +368,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " probe_type: 1", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -436,7 +384,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(2048), anInt(3)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -454,7 +402,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " program_length: 2048", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -474,7 +422,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(3), anInt(2048)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -495,7 +443,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " zero_lifetime_ras: 1", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -511,7 +459,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aLong(1000), aLong(-1)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -528,7 +476,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " router_lifetime: 2000", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -543,13 +491,4 @@ public class IpConnectivityEventBuilderTest extends TestCase { fail(e.toString()); } } - - static String joinLines(String ... elems) { - StringBuilder b = new StringBuilder(); - for (String s : elems) { - b.append(s); - b.append("\n"); - } - return b.toString(); - } } diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index 68786d0b42..fd81c90a05 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -138,6 +138,7 @@ public class IpConnectivityMetricsTest extends TestCase { } @SmallTest + // TODO: add NetdEventListenerService coverage too public void testEndToEndLogging() { // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. IpConnectivityLog logger = new IpConnectivityLog(mService.impl); @@ -177,7 +178,7 @@ public class IpConnectivityMetricsTest extends TestCase { logger.log(ev); } - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -279,7 +280,7 @@ public class IpConnectivityMetricsTest extends TestCase { " router_lifetime: 2000", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, getdump("flush")); } diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 0ab440641d..05c9767325 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -16,161 +16,161 @@ package com.android.server.connectivity; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.Network; -import android.net.metrics.ConnectStats; -import android.net.metrics.DnsEvent; -import android.net.metrics.INetdEventListener; -import android.net.metrics.IpConnectivityLog; -import android.os.Parcelable; -import android.os.RemoteException; -import android.system.OsConstants; -import android.test.suitebuilder.annotation.SmallTest; -import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; -import java.io.FileOutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.OptionalInt; -import java.util.stream.IntStream; -import junit.framework.TestCase; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; +import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO; +import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -public class NetdEventListenerServiceTest extends TestCase { - - // TODO: read from NetdEventListenerService after this constant is read from system property - static final int BATCH_SIZE = 100; - static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO; - // TODO: read from INetdEventListener - static final int RETURN_CODE = 1; - - static final byte[] EVENT_TYPES = new byte[BATCH_SIZE]; - static final byte[] RETURN_CODES = new byte[BATCH_SIZE]; - static final int[] LATENCIES = new int[BATCH_SIZE]; - static { - for (int i = 0; i < BATCH_SIZE; i++) { - EVENT_TYPES[i] = EVENT_TYPE; - RETURN_CODES[i] = RETURN_CODE; - LATENCIES[i] = i; - } - } +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.support.test.runner.AndroidJUnit4; +import android.system.OsConstants; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Base64; +import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch; +import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; +import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NetdEventListenerServiceTest { private static final String EXAMPLE_IPV4 = "192.0.2.1"; private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1"; NetdEventListenerService mNetdEventListenerService; + ConnectivityManager mCm; - @Mock ConnectivityManager mCm; - @Mock IpConnectivityLog mLog; - ArgumentCaptor mCallbackCaptor; - ArgumentCaptor mDnsEvCaptor; - + @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class); - mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); - mNetdEventListenerService = new NetdEventListenerService(mCm, mLog); - - verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture()); + mCm = mock(ConnectivityManager.class); + mNetdEventListenerService = new NetdEventListenerService(mCm); } - @SmallTest - public void testOneDnsBatch() throws Exception { - log(105, LATENCIES); - log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event + @Test + public void testDnsLogging() throws Exception { + NetworkCapabilities ncWifi = new NetworkCapabilities(); + NetworkCapabilities ncCell = new NetworkCapabilities(); + ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); + ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - verifyLoggedDnsEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES)); + when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi); + when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell); - log(106, Arrays.copyOfRange(LATENCIES, BATCH_SIZE - 1, BATCH_SIZE)); + dnsEvent(100, EVENT_GETADDRINFO, 0, 3456); + dnsEvent(100, EVENT_GETADDRINFO, 0, 267); + dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230); + dnsEvent(100, EVENT_GETADDRINFO, 3, 45); + dnsEvent(100, EVENT_GETADDRINFO, 1, 2111); + dnsEvent(100, EVENT_GETADDRINFO, 0, 450); + dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638); + dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300); + dnsEvent(101, EVENT_GETADDRINFO, 0, 56); + dnsEvent(101, EVENT_GETADDRINFO, 0, 78); + dnsEvent(101, EVENT_GETADDRINFO, 0, 14); + dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56); + dnsEvent(101, EVENT_GETADDRINFO, 0, 78); + dnsEvent(101, EVENT_GETADDRINFO, 0, 14); - mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); // reset argument captor - verifyLoggedDnsEvents( - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES)); + String got = flushStatistics(); + String want = String.join("\n", + "dropped_events: 0", + "events <", + " if_name: \"\"", + " link_layer: 0", + " network_id: 0", + " time_ms: 0", + " transports: 0", + " connect_statistics <", + " connect_blocking_count: 0", + " connect_count: 0", + " ipv6_addr_count: 0", + " >", + ">", + "events <", + " if_name: \"\"", + " link_layer: 4", + " network_id: 100", + " time_ms: 0", + " transports: 2", + " dns_lookup_batch <", + " event_types: 1", + " event_types: 1", + " event_types: 2", + " event_types: 1", + " event_types: 1", + " event_types: 1", + " event_types: 2", + " event_types: 2", + " latencies_ms: 3456", + " latencies_ms: 267", + " latencies_ms: 1230", + " latencies_ms: 45", + " latencies_ms: 2111", + " latencies_ms: 450", + " latencies_ms: 638", + " latencies_ms: 1300", + " return_codes: 0", + " return_codes: 0", + " return_codes: 22", + " return_codes: 3", + " return_codes: 1", + " return_codes: 0", + " return_codes: 200", + " return_codes: 178", + " >", + ">", + "events <", + " if_name: \"\"", + " link_layer: 2", + " network_id: 101", + " time_ms: 0", + " transports: 1", + " dns_lookup_batch <", + " event_types: 1", + " event_types: 1", + " event_types: 1", + " event_types: 2", + " event_types: 1", + " event_types: 1", + " latencies_ms: 56", + " latencies_ms: 78", + " latencies_ms: 14", + " latencies_ms: 56", + " latencies_ms: 78", + " latencies_ms: 14", + " return_codes: 0", + " return_codes: 0", + " return_codes: 0", + " return_codes: 0", + " return_codes: 0", + " return_codes: 0", + " >", + ">", + "version: 2\n"); + assertEquals(want, got); } - @SmallTest - public void testSeveralDmsBatches() throws Exception { - log(105, LATENCIES); - log(106, LATENCIES); - log(105, LATENCIES); - log(107, LATENCIES); - - verifyLoggedDnsEvents( - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); - } - - @SmallTest - public void testDnsBatchAndNetworkLost() throws Exception { - byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20); - byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20); - int[] latencies = Arrays.copyOf(LATENCIES, 20); - - log(105, LATENCIES); - log(105, latencies); - mCallbackCaptor.getValue().onLost(new Network(105)); - log(105, LATENCIES); - - verifyLoggedDnsEvents( - new DnsEvent(105, eventTypes, returnCodes, latencies), - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES)); - } - - @SmallTest - public void testConcurrentDnsBatchesAndDumps() throws Exception { - final long stop = System.currentTimeMillis() + 100; - final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null")); - new Thread() { - public void run() { - while (System.currentTimeMillis() < stop) { - mNetdEventListenerService.dump(pw); - } - } - }.start(); - - logDnsAsync(105, LATENCIES); - logDnsAsync(106, LATENCIES); - logDnsAsync(107, LATENCIES); - - verifyLoggedDnsEvents(500, - new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES), - new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES)); - } - - @SmallTest - public void testConcurrentDnsBatchesAndNetworkLoss() throws Exception { - logDnsAsync(105, LATENCIES); - Thread.sleep(10L); - // call onLost() asynchronously to logDnsAsync's onDnsEvent() calls. - mCallbackCaptor.getValue().onLost(new Network(105)); - - // do not verify batch with unpredictable length - verify(mLog, timeout(500).times(1)).log(any(Parcelable.class)); - } - - @SmallTest + @Test public void testConnectLogging() throws Exception { final int OK = 0; Thread[] logActions = { @@ -268,44 +268,18 @@ public class NetdEventListenerServiceTest extends TestCase { }); } - void log(int netId, int[] latencies) { - try { - for (int l : latencies) { - mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, - 0, 0); + void dnsEvent(int netId, int type, int result, int latency) throws Exception { + mNetdEventListenerService.onDnsEvent(netId, type, result, latency, "", null, 0, 0); + } + + Thread dumpAction(long durationMs) throws Exception { + final long stop = System.currentTimeMillis() + durationMs; + final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null")); + return new Thread(() -> { + while (System.currentTimeMillis() < stop) { + mNetdEventListenerService.dump(pw); } - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - void logDnsAsync(int netId, int[] latencies) { - new Thread(() -> log(netId, latencies)).start(); - } - - void verifyLoggedDnsEvents(DnsEvent... expected) { - verifyLoggedDnsEvents(0, expected); - } - - void verifyLoggedDnsEvents(int wait, DnsEvent... expectedEvents) { - verify(mLog, timeout(wait).times(expectedEvents.length)).log(mDnsEvCaptor.capture()); - for (DnsEvent got : mDnsEvCaptor.getAllValues()) { - OptionalInt index = IntStream.range(0, expectedEvents.length) - .filter(i -> dnsEventsEqual(expectedEvents[i], got)) - .findFirst(); - // Don't match same expected event more than once. - index.ifPresent(i -> expectedEvents[i] = null); - assertTrue(index.isPresent()); - } - } - - /** equality function for DnsEvent to avoid overriding equals() and hashCode(). */ - static boolean dnsEventsEqual(DnsEvent expected, DnsEvent got) { - return (expected == got) || ((expected != null) && (got != null) - && (expected.netId == got.netId) - && Arrays.equals(expected.eventTypes, got.eventTypes) - && Arrays.equals(expected.returnCodes, got.returnCodes) - && Arrays.equals(expected.latenciesMs, got.latenciesMs)); + }); } static void verifyConnectEvent(String expected, IpConnectivityEvent got) { @@ -318,4 +292,17 @@ public class NetdEventListenerServiceTest extends TestCase { fail(e.toString()); } } + + // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto. + String flushStatistics() throws Exception { + IpConnectivityMetrics metricsService = + new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000); + metricsService.mNetdListener = mNetdEventListenerService; + + StringWriter buffer = new StringWriter(); + PrintWriter writer = new PrintWriter(buffer); + metricsService.impl.dump(null, writer, new String[]{"flush"}); + byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT); + return IpConnectivityLog.parseFrom(bytes).toString(); + } }