15
15
package com .google .firebase .perf .application ;
16
16
17
17
import static org .mockito .ArgumentMatchers .any ;
18
+ import static org .mockito .ArgumentMatchers .nullable ;
18
19
import static org .mockito .Mockito .doAnswer ;
20
+ import static org .mockito .Mockito .doReturn ;
21
+ import static org .mockito .Mockito .spy ;
19
22
import static org .mockito .Mockito .times ;
20
23
import static org .mockito .Mockito .verify ;
21
24
import static org .mockito .MockitoAnnotations .initMocks ;
28
31
import com .google .firebase .perf .FirebasePerformanceTestBase ;
29
32
import com .google .firebase .perf .config .ConfigResolver ;
30
33
import com .google .firebase .perf .config .DeviceCacheManager ;
34
+ import com .google .firebase .perf .metrics .Trace ;
31
35
import com .google .firebase .perf .transport .TransportManager ;
32
36
import com .google .firebase .perf .util .Clock ;
33
37
import com .google .firebase .perf .util .Timer ;
34
38
import com .google .firebase .perf .v1 .TraceMetric ;
35
39
import com .google .testing .timing .FakeDirectExecutorService ;
40
+ import java .util .WeakHashMap ;
41
+ import org .junit .Assert ;
36
42
import org .junit .Before ;
37
43
import org .junit .Test ;
38
44
import org .junit .runner .RunWith ;
@@ -48,17 +54,21 @@ public class FragmentStateMonitorTest extends FirebasePerformanceTestBase {
48
54
49
55
@ Mock private Clock clock ;
50
56
@ Mock private Fragment mockFragment ;
51
- @ Mock private FragmentManager mockfragmentManager ;
57
+ @ Mock private FragmentManager mockFragmentManager ;
52
58
@ Mock private TransportManager mockTransportManager ;
53
59
@ Mock private AppCompatActivity mockActivity ;
60
+ @ Mock private AppCompatActivity mockActivityB ;
54
61
@ Mock private AppStateMonitor appStateMonitor ;
55
62
@ Mock private FrameMetricsAggregator fma ;
56
63
57
64
@ Captor private ArgumentCaptor <TraceMetric > argTraceMetric ;
58
65
59
66
private long currentTime = 0 ;
67
+ private static final String longFragmentName =
68
+ "_st_NeverGonnaGiveYouUpNeverGonnaLetYouDownNeverGonnaRunAroundAndDesertYouNeverGonnaMakeYouCryNeverGonnaSayGoodbyeNeverGonnaTellALieAndHurtYou" ;
60
69
61
70
private Activity activity1 ;
71
+ private ConfigResolver configResolver ;
62
72
63
73
@ Before
64
74
public void setUp () {
@@ -71,16 +81,93 @@ public void setUp() {
71
81
72
82
ConfigResolver configResolver = ConfigResolver .getInstance ();
73
83
configResolver .setDeviceCacheManager (new DeviceCacheManager (new FakeDirectExecutorService ()));
84
+ ConfigResolver spyConfigResolver = spy (configResolver );
85
+ doReturn (true ).when (spyConfigResolver ).isPerformanceMonitoringEnabled ();
86
+ this .configResolver = spyConfigResolver ;
74
87
}
75
88
89
+ /************ Trace Creation Tests ****************/
90
+
76
91
@ Test
77
- public void fragmentLifecycleCallbacks_logFragmentScreenTrace () {
92
+ public void lifecycleCallbacks_logFragmentScreenTrace () {
78
93
FragmentStateMonitor monitor =
79
94
new FragmentStateMonitor (clock , mockTransportManager , appStateMonitor , fma );
80
- monitor .onFragmentResumed (mockfragmentManager , mockFragment );
95
+ monitor .onFragmentResumed (mockFragmentManager , mockFragment );
81
96
verify (mockTransportManager , times (0 )).log (any (TraceMetric .class ), any ());
82
97
83
- monitor .onFragmentPaused (mockfragmentManager , mockFragment );
98
+ monitor .onFragmentPaused (mockFragmentManager , mockFragment );
99
+ verify (mockTransportManager , times (1 )).log (any (TraceMetric .class ), any ());
100
+
101
+ monitor .onFragmentResumed (mockFragmentManager , mockFragment );
84
102
verify (mockTransportManager , times (1 )).log (any (TraceMetric .class ), any ());
103
+
104
+ monitor .onFragmentResumed (mockFragmentManager , mockFragment );
105
+ verify (mockTransportManager , times (2 )).log (any (TraceMetric .class ), any ());
106
+ }
107
+
108
+ @ Test
109
+ public void lifecycleCallbacks_cleansUpMap_duringActivityTransitions () {
110
+ // Simulate call order of activity + fragment lifecycle events
111
+ AppStateMonitor appStateMonitor =
112
+ spy (new AppStateMonitor (mockTransportManager , clock , configResolver , fma ));
113
+ FragmentStateMonitor fragmentMonitor =
114
+ new FragmentStateMonitor (clock , mockTransportManager , appStateMonitor , fma );
115
+ doReturn (true ).when (appStateMonitor ).isScreenTraceSupported ();
116
+ WeakHashMap <Fragment , Trace > map = fragmentMonitor .getFragmentToTraceMap ();
117
+ // Activity_A onCreate registers FragmentStateMonitor, then:
118
+ appStateMonitor .onActivityStarted (mockActivity );
119
+ Assert .assertEquals (0 , map .size ());
120
+ appStateMonitor .onActivityResumed (mockActivity );
121
+ fragmentMonitor .onFragmentResumed (mockFragmentManager , mockFragment );
122
+ Assert .assertEquals (1 , map .size ());
123
+ appStateMonitor .onActivityPaused (mockActivity );
124
+ fragmentMonitor .onFragmentPaused (mockFragmentManager , mockFragment );
125
+ Assert .assertEquals (0 , map .size ());
126
+ appStateMonitor .onActivityPostPaused (mockActivity );
127
+ // Activity_B onCreate registers FragmentStateMonitor, then:
128
+ appStateMonitor .onActivityStarted (mockActivityB );
129
+ appStateMonitor .onActivityResumed (mockActivityB );
130
+ fragmentMonitor .onFragmentResumed (mockFragmentManager , mockFragment );
131
+ appStateMonitor .onActivityStopped (mockActivity );
132
+ Assert .assertEquals (1 , map .size ());
133
+ }
134
+
135
+ @ Test
136
+ public void fragmentTraceCreation_truncatesName_whenFragmentNameTooLong () {
137
+ AppStateMonitor appStateMonitor =
138
+ spy (new AppStateMonitor (mockTransportManager , clock , configResolver , fma ));
139
+ FragmentStateMonitor fragmentMonitor =
140
+ spy (new FragmentStateMonitor (clock , mockTransportManager , appStateMonitor , fma ));
141
+ doReturn (true ).when (appStateMonitor ).isScreenTraceSupported ();
142
+ doReturn (longFragmentName )
143
+ .when (fragmentMonitor )
144
+ .getFragmentScreenTraceName (nullable (Fragment .class ));
145
+
146
+ fragmentMonitor .onFragmentResumed (mockFragmentManager , mockFragment );
147
+ fragmentMonitor .onFragmentPaused (mockFragmentManager , mockFragment );
148
+ }
149
+
150
+ /************ FrameMetrics Collection Tests ****************/
151
+
152
+ @ Test
153
+ public void onFragmentPaused_processFrameMetrics_beforeReset () {
154
+ // Simulate call order of activity + fragment lifecycle events
155
+ AppStateMonitor appStateMonitor =
156
+ spy (new AppStateMonitor (mockTransportManager , clock , configResolver , fma ));
157
+ FragmentStateMonitor fragmentMonitor =
158
+ new FragmentStateMonitor (clock , mockTransportManager , appStateMonitor , fma );
159
+ doReturn (true ).when (appStateMonitor ).isScreenTraceSupported ();
160
+ // Activity_A onCreate registers FragmentStateMonitor, then:
161
+ appStateMonitor .onActivityStarted (mockActivity );
162
+ appStateMonitor .onActivityResumed (mockActivity );
163
+ fragmentMonitor .onFragmentResumed (mockFragmentManager , mockFragment );
164
+ appStateMonitor .onActivityPaused (mockActivity );
165
+ // reset() was not called at the time of fragments collecting its frame metrics
166
+ verify (fma , times (0 )).reset ();
167
+ fragmentMonitor .onFragmentPaused (mockFragmentManager , mockFragment );
168
+ verify (fma , times (0 )).reset ();
169
+ // reset() is only called after fragment is done collecting its metrics
170
+ appStateMonitor .onActivityPostPaused (mockActivity );
171
+ verify (fma , times (1 )).reset ();
85
172
}
86
173
}
0 commit comments