1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.N;
4 import static com.google.common.truth.Truth.assertThat;
5 
6 import android.os.health.HealthStats;
7 import android.os.health.TimerStat;
8 import android.util.ArrayMap;
9 import androidx.test.ext.junit.runners.AndroidJUnit4;
10 import com.google.common.primitives.Ints;
11 import java.util.HashSet;
12 import org.junit.Test;
13 import org.junit.runner.RunWith;
14 import org.robolectric.annotation.Config;
15 
16 @RunWith(AndroidJUnit4.class)
17 @Config(minSdk = N)
18 public class HealthStatsBuilderTest {
19 
20   private static final int KEY_1 = 867;
21   private static final int KEY_2 = 5309;
22 
23   private static final TimerStat TIMER_STAT_1 = new TimerStat(42, 64);
24   private static final TimerStat TIMER_STAT_2 = new TimerStat(5, 7);
25 
26   private static final long MEASUREMENT_1 = 13;
27   private static final long MEASUREMENT_2 = 17;
28 
29   private static final String MAP_STRING_1 = "map_string_1";
30   private static final String MAP_STRING_2 = "map_string_2";
31 
32   private static final ArrayMap<String, Long> MEASUREMENTS_MAP = new ArrayMap<>();
33   private static final long MEASUREMENTS_VALUE_1 = 19;
34   private static final long MEASUREMENTS_VALUE_2 = 21;
35 
36   private static final ArrayMap<String, HealthStats> STATS_MAP = new ArrayMap<>();
37   private static final HealthStats STATS_VALUE_1 =
38       HealthStatsBuilder.newBuilder().setDataType("23").build();
39   private static final HealthStats STATS_VALUE_2 =
40       HealthStatsBuilder.newBuilder().setDataType("27").build();
41 
42   private static final ArrayMap<String, TimerStat> TIMERS_MAP = new ArrayMap<>();
43   private static final TimerStat TIMERS_VALUE_1 = new TimerStat(29, 31);
44   private static final TimerStat TIMERS_VALUE_2 = new TimerStat(37, 41);
45 
46   static {
MEASUREMENTS_MAP.put(MAP_STRING_1, MEASUREMENTS_VALUE_1)47     MEASUREMENTS_MAP.put(MAP_STRING_1, MEASUREMENTS_VALUE_1);
MEASUREMENTS_MAP.put(MAP_STRING_2, MEASUREMENTS_VALUE_2)48     MEASUREMENTS_MAP.put(MAP_STRING_2, MEASUREMENTS_VALUE_2);
49 
STATS_MAP.put(MAP_STRING_1, STATS_VALUE_1)50     STATS_MAP.put(MAP_STRING_1, STATS_VALUE_1);
STATS_MAP.put(MAP_STRING_2, STATS_VALUE_2)51     STATS_MAP.put(MAP_STRING_2, STATS_VALUE_2);
52 
TIMERS_MAP.put(MAP_STRING_1, TIMERS_VALUE_1)53     TIMERS_MAP.put(MAP_STRING_1, TIMERS_VALUE_1);
TIMERS_MAP.put(MAP_STRING_2, TIMERS_VALUE_2)54     TIMERS_MAP.put(MAP_STRING_2, TIMERS_VALUE_2);
55   }
56 
57   @Test
emptyBuilder_isEmpty()58   public void emptyBuilder_isEmpty() {
59     HealthStats stats = HealthStatsBuilder.newBuilder().build();
60 
61     assertThat(stats.getDataType()).isNull();
62     assertThat(stats.getMeasurementKeyCount()).isEqualTo(0);
63     assertThat(stats.getMeasurementsKeyCount()).isEqualTo(0);
64     assertThat(stats.getStatsKeyCount()).isEqualTo(0);
65     assertThat(stats.getTimerKeyCount()).isEqualTo(0);
66     assertThat(stats.getTimersKeyCount()).isEqualTo(0);
67   }
68 
69   @Test
setEverything_everythingSetsCorrectly()70   public void setEverything_everythingSetsCorrectly() {
71     HealthStats stats =
72         HealthStatsBuilder.newBuilder()
73             .setDataType("arbitrary_data_type")
74             .addTimerStat(KEY_1, TIMER_STAT_1)
75             .addTimerStat(KEY_2, TIMER_STAT_2)
76             .addMeasurement(KEY_1, MEASUREMENT_1)
77             .addMeasurement(KEY_2, MEASUREMENT_2)
78             .addStats(KEY_1, STATS_MAP)
79             .addTimers(KEY_1, TIMERS_MAP)
80             .addMeasurements(KEY_1, MEASUREMENTS_MAP)
81             .build();
82 
83     assertThat(stats.getDataType()).isEqualTo("arbitrary_data_type");
84 
85     assertThat(stats.getTimerKeyCount()).isEqualTo(2);
86     assertThat(stats.hasTimer(KEY_1)).isTrue();
87     assertThat(stats.getTimerCount(KEY_1)).isEqualTo(TIMER_STAT_1.getCount());
88     assertThat(stats.getTimerTime(KEY_1)).isEqualTo(TIMER_STAT_1.getTime());
89     compareTimers(stats.getTimer(KEY_1), TIMER_STAT_1);
90     assertThat(stats.hasTimer(KEY_2)).isTrue();
91     assertThat(stats.getTimerCount(KEY_2)).isEqualTo(TIMER_STAT_2.getCount());
92     assertThat(stats.getTimerTime(KEY_2)).isEqualTo(TIMER_STAT_2.getTime());
93     compareTimers(stats.getTimer(KEY_2), TIMER_STAT_2);
94 
95     assertThat(stats.getMeasurementKeyCount()).isEqualTo(2);
96     assertThat(stats.hasMeasurement(KEY_1)).isTrue();
97     assertThat(stats.getMeasurement(KEY_1)).isEqualTo(MEASUREMENT_1);
98     assertThat(stats.hasMeasurement(KEY_2)).isTrue();
99     assertThat(stats.getMeasurement(KEY_2)).isEqualTo(MEASUREMENT_2);
100 
101     assertThat(stats.getMeasurementsKeyCount()).isEqualTo(1);
102     assertThat(stats.hasMeasurements(KEY_1)).isTrue();
103     assertThat(stats.getMeasurements(KEY_1)).isEqualTo(MEASUREMENTS_MAP);
104 
105     assertThat(stats.getStatsKeyCount()).isEqualTo(1);
106     assertThat(stats.hasStats(KEY_1)).isTrue();
107     assertThat(stats.getStats(KEY_1)).isEqualTo(STATS_MAP);
108 
109     assertThat(stats.getTimersKeyCount()).isEqualTo(1);
110     assertThat(stats.hasTimers(KEY_1)).isTrue();
111     assertThat(stats.getTimers(KEY_1)).isEqualTo(TIMERS_MAP);
112   }
113 
114   @Test
healthStats_keysAreIterable()115   public void healthStats_keysAreIterable() {
116     HealthStats stats =
117         HealthStatsBuilder.newBuilder()
118             .setDataType("arbitrary_data_type")
119             .addMeasurement(KEY_1, MEASUREMENT_1)
120             .addMeasurement(KEY_2, MEASUREMENT_2)
121             .build();
122 
123     assertThat(stats.getMeasurementKeyCount()).isEqualTo(2);
124     for (int i = 0; i < stats.getMeasurementKeyCount(); i++) {
125       int key = stats.getMeasurementKeyAt(i);
126       switch (key) {
127         case KEY_1:
128           assertThat(stats.getMeasurement(key)).isEqualTo(MEASUREMENT_1);
129           break;
130         case KEY_2:
131           assertThat(stats.getMeasurement(key)).isEqualTo(MEASUREMENT_2);
132           break;
133         default:
134           throw new IllegalStateException("Unexpected HealthStats key");
135       }
136     }
137   }
138 
139   @Test
toSortedIntArray_resultIsSorted()140   public void toSortedIntArray_resultIsSorted() {
141     HashSet<Integer> set = new HashSet<>();
142     set.add(1);
143     set.add(2);
144     set.add(3);
145     ReverseIteratingSet reversedSet = new ReverseIteratingSet(set);
146 
147     int[] setAsSortedArray = HealthStatsBuilder.toSortedIntArray(set);
148     int[] reversedSetAsSortedArray = HealthStatsBuilder.toSortedIntArray(reversedSet);
149 
150     assertThat(Ints.asList(setAsSortedArray)).isInStrictOrder();
151     assertThat(Ints.asList(reversedSetAsSortedArray)).isInStrictOrder();
152   }
153 
compareTimers(TimerStat timer1, TimerStat timer2)154   private final void compareTimers(TimerStat timer1, TimerStat timer2) {
155     assertThat(timer1.getCount()).isEqualTo(timer2.getCount());
156     assertThat(timer1.getTime()).isEqualTo(timer2.getTime());
157   }
158 
159   // Identical to HashSet<Integer>, except that the result of toArray() is reversed.
160   private static final class ReverseIteratingSet extends HashSet<Integer> {
ReverseIteratingSet(HashSet<Integer> c)161     public ReverseIteratingSet(HashSet<Integer> c) {
162       super(c);
163     }
164 
165     @Override
toArray()166     public Object[] toArray() {
167       Object[] forward = super.toArray();
168       Object[] backward = new Object[forward.length];
169       for (int i = 0; i < forward.length; i++) {
170         backward[i] = forward[forward.length - 1 - i];
171       }
172       return backward;
173     }
174   }
175 }
176