1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settingslib.net; 18 19 import static android.app.usage.NetworkStats.Bucket.UID_ALL; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertThrows; 23 import static org.mockito.Mockito.doNothing; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.app.usage.NetworkStats; 30 import android.app.usage.NetworkStatsManager; 31 import android.content.Context; 32 import android.net.ConnectivityManager; 33 import android.net.NetworkPolicy; 34 import android.net.NetworkPolicyManager; 35 import android.net.NetworkTemplate; 36 import android.text.format.DateUtils; 37 import android.util.Range; 38 39 import androidx.annotation.NonNull; 40 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.mockito.Mock; 45 import org.mockito.MockitoAnnotations; 46 import org.robolectric.RobolectricTestRunner; 47 import org.robolectric.util.ReflectionHelpers; 48 49 import java.time.ZonedDateTime; 50 import java.util.ArrayList; 51 import java.util.Iterator; 52 import java.util.List; 53 import java.util.Queue; 54 import java.util.concurrent.LinkedBlockingQueue; 55 56 @RunWith(RobolectricTestRunner.class) 57 public class NetworkCycleDataLoaderTest { 58 59 @Mock 60 private NetworkStatsManager mNetworkStatsManager; 61 @Mock 62 private NetworkPolicyManager mNetworkPolicyManager; 63 @Mock 64 private Context mContext; 65 @Mock 66 private NetworkPolicy mPolicy; 67 @Mock 68 private Iterator<Range<ZonedDateTime>> mIterator; 69 70 private NetworkCycleDataTestLoader mLoader; 71 72 @Before setUp()73 public void setUp() { 74 MockitoAnnotations.initMocks(this); 75 when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE)) 76 .thenReturn(mNetworkStatsManager); 77 when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE)) 78 .thenReturn(mNetworkPolicyManager); 79 when(mPolicy.cycleIterator()).thenReturn(mIterator); 80 when(mNetworkPolicyManager.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]); 81 } 82 83 @Test loadInBackground_noNetworkPolicy_shouldLoad4WeeksData()84 public void loadInBackground_noNetworkPolicy_shouldLoad4WeeksData() { 85 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 86 doNothing().when(mLoader).loadFourWeeksData(); 87 88 mLoader.loadInBackground(); 89 90 verify(mLoader).loadFourWeeksData(); 91 } 92 93 @Test loadInBackground_hasNetworkPolicy_shouldLoadPolicyData()94 public void loadInBackground_hasNetworkPolicy_shouldLoadPolicyData() { 95 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 96 ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy); 97 98 mLoader.loadInBackground(); 99 100 verify(mLoader).loadPolicyData(); 101 } 102 103 @Test loadInBackground_hasCyclePeriod_shouldLoadDataForSpecificCycles()104 public void loadInBackground_hasCyclePeriod_shouldLoadDataForSpecificCycles() { 105 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 106 doNothing().when(mLoader).loadDataForSpecificCycles(); 107 final ArrayList<Long> cycles = new ArrayList<>(); 108 cycles.add(67890L); 109 cycles.add(12345L); 110 ReflectionHelpers.setField(mLoader, "mCycles", cycles); 111 112 mLoader.loadInBackground(); 113 114 verify(mLoader).loadDataForSpecificCycles(); 115 } 116 117 @Test loadPolicyData_shouldRecordUsageFromPolicyCycle()118 public void loadPolicyData_shouldRecordUsageFromPolicyCycle() { 119 final int networkType = ConnectivityManager.TYPE_MOBILE; 120 final String subId = "TestSubscriber"; 121 final ZonedDateTime now = ZonedDateTime.now(); 122 final Range<ZonedDateTime> cycle = new Range<>(now, now); 123 final long nowInMs = now.toInstant().toEpochMilli(); 124 // mock 1 cycle data. 125 // hasNext() will be called internally in next(), hence setting it to return true twice. 126 when(mIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); 127 when(mIterator.next()).thenReturn(cycle); 128 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 129 ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy); 130 131 mLoader.loadPolicyData(); 132 133 verify(mLoader).recordUsage(nowInMs, nowInMs); 134 } 135 makeMockBucket(int uid, long rxBytes, long txBytes, long start, long end)136 private NetworkStats.Bucket makeMockBucket(int uid, long rxBytes, long txBytes, 137 long start, long end) { 138 NetworkStats.Bucket ret = mock(NetworkStats.Bucket.class); 139 when(ret.getUid()).thenReturn(uid); 140 when(ret.getRxBytes()).thenReturn(rxBytes); 141 when(ret.getTxBytes()).thenReturn(txBytes); 142 when(ret.getStartTimeStamp()).thenReturn(start); 143 when(ret.getEndTimeStamp()).thenReturn(end); 144 return ret; 145 } 146 147 @Test loadFourWeeksData_shouldRecordUsageForLast4Weeks()148 public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() { 149 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 150 final long now = System.currentTimeMillis(); 151 final long fourWeeksAgo = now - (DateUtils.WEEK_IN_MILLIS * 4); 152 final long twoDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 2); 153 mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, twoDaysAgo, now)); 154 155 mLoader.loadFourWeeksData(); 156 157 verify(mLoader).recordUsage(fourWeeksAgo, now); 158 } 159 160 @Test loadDataForSpecificCycles_shouldRecordUsageForSpecifiedTime()161 public void loadDataForSpecificCycles_shouldRecordUsageForSpecifiedTime() { 162 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 163 final long now = System.currentTimeMillis(); 164 final long tenDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 10); 165 final long twentyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 20); 166 final long thirtyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 30); 167 final ArrayList<Long> cycles = new ArrayList<>(); 168 cycles.add(now); 169 cycles.add(tenDaysAgo); 170 cycles.add(twentyDaysAgo); 171 cycles.add(thirtyDaysAgo); 172 ReflectionHelpers.setField(mLoader, "mCycles", cycles); 173 174 mLoader.loadDataForSpecificCycles(); 175 176 verify(mLoader).recordUsage(tenDaysAgo, now); 177 verify(mLoader).recordUsage(twentyDaysAgo, tenDaysAgo); 178 verify(mLoader).recordUsage(thirtyDaysAgo, twentyDaysAgo); 179 } 180 181 @Test getTimeRangeOf()182 public void getTimeRangeOf() { 183 mLoader = spy(new NetworkCycleDataTestLoader(mContext)); 184 // If empty, new Range(MAX_VALUE, MIN_VALUE) will be constructed. Hence, the function 185 // should throw. 186 assertThrows(IllegalArgumentException.class, 187 () -> mLoader.getTimeRangeOf(mock(NetworkStats.class))); 188 189 mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10)); 190 // Feed the function with unused NetworkStats. The actual data injection is 191 // done by addBucket. 192 assertEquals(new Range(0L, 10L), mLoader.getTimeRangeOf(mock(NetworkStats.class))); 193 194 mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10)); 195 mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 30, 40)); 196 mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 10, 25)); 197 assertEquals(new Range(0L, 40L), mLoader.getTimeRangeOf(mock(NetworkStats.class))); 198 } 199 200 public class NetworkCycleDataTestLoader extends NetworkCycleDataLoader<List<NetworkCycleData>> { 201 private final Queue<NetworkStats.Bucket> mMockedBuckets = new LinkedBlockingQueue<>(); 202 NetworkCycleDataTestLoader(Context context)203 private NetworkCycleDataTestLoader(Context context) { 204 super(NetworkCycleDataLoader.builder(mContext) 205 .setNetworkTemplate(mock(NetworkTemplate.class))); 206 mContext = context; 207 } 208 209 @Override recordUsage(long start, long end)210 void recordUsage(long start, long end) { 211 } 212 213 @Override getCycleUsage()214 List<NetworkCycleData> getCycleUsage() { 215 return null; 216 } 217 addBucket(NetworkStats.Bucket bucket)218 public void addBucket(NetworkStats.Bucket bucket) { 219 mMockedBuckets.add(bucket); 220 } 221 222 @Override hasNextBucket(@onNull NetworkStats unused)223 public boolean hasNextBucket(@NonNull NetworkStats unused) { 224 return !mMockedBuckets.isEmpty(); 225 } 226 227 @Override getNextBucket(@onNull NetworkStats unused)228 public NetworkStats.Bucket getNextBucket(@NonNull NetworkStats unused) { 229 return mMockedBuckets.remove(); 230 } 231 } 232 } 233