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 package com.android.settings.datausage; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.mockito.Mockito.mock; 20 import static org.mockito.Mockito.spy; 21 import static org.mockito.Mockito.verify; 22 import static org.mockito.Mockito.when; 23 24 import android.content.Context; 25 import android.net.NetworkStatsHistory; 26 import android.net.NetworkStatsHistory.Entry; 27 import android.util.SparseIntArray; 28 import com.android.settings.graph.UsageView; 29 import com.android.settings.testutils.SettingsRobolectricTestRunner; 30 import org.junit.Before; 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.mockito.ArgumentCaptor; 34 import org.mockito.MockitoAnnotations; 35 import org.robolectric.RuntimeEnvironment; 36 37 @RunWith(SettingsRobolectricTestRunner.class) 38 public class ChartDataUsagePreferenceTest { 39 40 private static final long MILLIS_IN_ONE_HOUR = 60 * 60 * 1000; 41 private static final long MILLIS_IN_ONE_DAY = 24 * MILLIS_IN_ONE_HOUR; 42 private static final long TIMESTAMP_NOW = Integer.MAX_VALUE; 43 44 private NetworkStatsHistory mNetworkStatsHistory; 45 private Context mContext; 46 private ChartDataUsagePreference mPreference; 47 48 @Before setUp()49 public void setUp() { 50 MockitoAnnotations.initMocks(this); 51 52 mContext = RuntimeEnvironment.application; 53 mPreference = new ChartDataUsagePreference(mContext, null); 54 mNetworkStatsHistory = spy(new NetworkStatsHistory(MILLIS_IN_ONE_HOUR, 10)); 55 addTestNetworkEntries(); 56 mPreference.setNetworkStats(mNetworkStatsHistory); 57 } 58 59 @Test calcPoints_notStartOfData_shouldAddDataPointsOnly()60 public void calcPoints_notStartOfData_shouldAddDataPointsOnly() { 61 final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY; 62 final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY; 63 mPreference.setVisibleRange(start, end); 64 when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(2); 65 when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(7); 66 final UsageView usageView = mock(UsageView.class); 67 final ArgumentCaptor<SparseIntArray> pointsCaptor = 68 ArgumentCaptor.forClass(SparseIntArray.class); 69 70 mPreference.calcPoints(usageView); 71 72 verify(usageView).addPath(pointsCaptor.capture()); 73 SparseIntArray points = pointsCaptor.getValue(); 74 // the point should be normal usage data 75 assertThat(points.valueAt(1)).isNotEqualTo(-1); 76 } 77 78 @Test calcPoints_startOfData_shouldIndicateStartOfData()79 public void calcPoints_startOfData_shouldIndicateStartOfData() { 80 final long start = TIMESTAMP_NOW - 20 * MILLIS_IN_ONE_DAY; 81 final long end = TIMESTAMP_NOW - 5 * MILLIS_IN_ONE_DAY; 82 mPreference.setVisibleRange(start, end); 83 when(mNetworkStatsHistory.getIndexAfter(start)).thenReturn(0); 84 when(mNetworkStatsHistory.getIndexAfter(end)).thenReturn(5); 85 final UsageView usageView = mock(UsageView.class); 86 final ArgumentCaptor<SparseIntArray> pointsCaptor = 87 ArgumentCaptor.forClass(SparseIntArray.class); 88 89 mPreference.calcPoints(usageView); 90 91 verify(usageView).addPath(pointsCaptor.capture()); 92 SparseIntArray points = pointsCaptor.getValue(); 93 // indicator that no data is available 94 assertThat(points.keyAt(1)).isEqualTo(points.keyAt(2) - 1); 95 assertThat(points.valueAt(1)).isEqualTo(-1); 96 } 97 addTestNetworkEntries()98 private void addTestNetworkEntries() { 99 // create 10 arbitary network data 100 mNetworkStatsHistory.setValues(0, createEntry(1521583200000L, 743823454L, 16574289L)); 101 mNetworkStatsHistory.setValues(1, createEntry(1521586800000L, 64396L, 160364L)); 102 mNetworkStatsHistory.setValues(2, createEntry(1521590400000L, 2832L, 5299L)); 103 mNetworkStatsHistory.setValues(3, createEntry(1521655200000L, 83849690L, 3558238L)); 104 mNetworkStatsHistory.setValues(4, createEntry(1521658800000L, 1883657L, 353330L)); 105 mNetworkStatsHistory.setValues(5, createEntry(1521662400000L, 705259L, 279065L)); 106 mNetworkStatsHistory.setValues(6, createEntry(1521666000000L, 216169L, 155302L)); 107 mNetworkStatsHistory.setValues(7, createEntry(1521669600000L, 6069175L, 427581L)); 108 mNetworkStatsHistory.setValues(8, createEntry(1521673200000L, 120389L, 110807L)); 109 mNetworkStatsHistory.setValues(9, createEntry(1521676800000L, 29947L, 73257L)); 110 } 111 112 /** 113 * Create a network entry to be used to calculate the usage chart. In the calculation, we only 114 * need bucketStart, total bytes (rx + tx), and bucketDuration (which is set when we create 115 * the NetworkStatsHistory object). Other fields are ignored, so we don't initialize here. 116 * @param start the timestamp when this entry begins 117 * @param rx the total number of received bytes 118 * @param tx the total number of transmitted bytes 119 * @return the network entry with the corresponding start time and data usage 120 */ createEntry(long start, long rx, long tx)121 private Entry createEntry(long start, long rx, long tx) { 122 Entry entry = new Entry(); 123 entry.bucketStart = start; 124 entry.rxBytes = rx; 125 entry.txBytes = tx; 126 return entry; 127 } 128 } 129